﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using OneLine.Components;

namespace OneLine
{
    public class PieMenu
    {
        private bool visible;

        public bool Visible
        {
            get { return visible; }
            set { visible = value; }
        }

        private PieMenuNode rootNode;

        public PieMenuNode RootNode
        {
            get { return rootNode; }
            set { rootNode = value; }
        }

        private float radius = 100;

        public float Radius
        {
            get { return radius; }
            set { radius = value; }
        }

        Transition t;
        public PieMenu()
        {
            t = new Transition(Direction.Ascending, TransitionCurve.Linear, 0.3f);
            hideDelegate = new SimpleDelegate(this.OnHide);
            newMenuDelegate = new SimpleDelegate(this.NewMenu);
        }


        int selectionIndex = -1;
        private Vector2 drawPosition;

        public Vector2 Position
        {
            get { return drawPosition; }
            set { drawPosition = value; }
        }

        public void Draw(SpriteBatch spriteBatch, SpriteFont font)
        {
            if (!visible)
                return;

            Vector2 center = drawPosition;
            spriteBatch.Begin();

            float scale = t.CurrentPosition;

            float currentAngle = MathHelper.PiOver2;

            float angleIncrement = MathHelper.TwoPi / rootNode.Children.Count;
            for (int i = 0; i < rootNode.Children.Count; i++)
            {
                Vector2 imagePos = center + scale * radius * new Vector2((float)Math.Cos(currentAngle), -(float)Math.Sin(currentAngle));

                int imageSize = (int)(scale * 30.0f);
                Rectangle destinationRect = new Rectangle((int)imagePos.X - imageSize, (int)imagePos.Y - imageSize, 2 * imageSize, 2 * imageSize);

                Color drawColor = Color.White;
                float testCAngle = currentAngle;
                if (currentAngle <= 0)
                    currentAngle += MathHelper.TwoPi;
                if (i == selectionIndex)
                    drawColor = Color.Red;
                spriteBatch.Draw(rootNode.Children[i].Icon, destinationRect, drawColor);
                if (i == selectionIndex)
                    spriteBatch.DrawString(font, rootNode.Children[i].Text, imagePos + new Vector2(-font.MeasureString(rootNode.Children[i].Text).X / 2, imageSize), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0);

                //if selected (how do I detect that?), show the description ar some edge
                // and show it highlighted

                currentAngle -= angleIncrement;
            }

            spriteBatch.End();

        }
        public void Update(GameTime gameTime)
        {
            if (!visible)
                return;
            t.Update(gameTime.ElapsedGameTime.TotalSeconds);
        }

        protected void ComputeSelected(Vector2 selectionVector)
        {
            selectionIndex = -1;
            //System.Diagnostics.Debug.WriteLine(selectionVector.Length());
            if (selectionVector.Length() > 100.0f)
                return;
            if (selectionVector.Length() > 0.3f)
            {
                float angleDivision = 1.0f / rootNode.Children.Count;

                float angle = (float)Math.Atan2(selectionVector.Y, selectionVector.X);
                if (angle < 0.0f)
                    angle += MathHelper.TwoPi; //now angle is between 0 and TwoPi

                angle /= MathHelper.TwoPi;
                angle = 1.0f - angle;

                float rotationBegins = 0.75f - angleDivision / 2.0f;

                if (angle <= rotationBegins)
                    angle += 1.0f;

                angle -= rotationBegins;

                selectionIndex = 0;
                while (selectionIndex * angleDivision < angle)
                {
                    selectionIndex++;
                }
                selectionIndex--;

            }

        }
        public bool HandleInput(Input input, Vector2 selectionVector)
        {
            if (!visible)
                return false;
            selectionVector.X *= -1f;
            ComputeSelected(selectionVector);

            if (input.InGameSelect)
            {
                if (selectionIndex >= 0)
                {
                    if (rootNode.Children[selectionIndex].IsLeaf)
                    {
                        rootNode.Children[selectionIndex].Select();
                        ChangeTo(null);
                    }
                    else
                        ChangeTo(rootNode.Children[selectionIndex]);
                }
                else
                    ChangeTo(rootNode.parent);
            }

            if (input.MenuCancel)
            {
                ChangeTo(rootNode.parent);
            }


            return true;
        }

        SimpleDelegate hideDelegate;
        SimpleDelegate newMenuDelegate;
        private void OnHide(Object sender)
        {
            this.visible = false;
            t.OnTransitionEnd = null;
        }
        PieMenuNode newMenuNode;
        private void NewMenu(Object sender)
        {
            rootNode = newMenuNode;
            t.Reset(Direction.Ascending);
            t.OnTransitionEnd = null;
        }
        private void ChangeTo(PieMenuNode newNode)
        {
            if (newNode == null)
            {
                t.OnTransitionEnd = hideDelegate;
                t.Reset(Direction.Descending);
            }
            else
            {
                t.OnTransitionEnd = newMenuDelegate;
                newMenuNode = newNode;
                t.Reset(Direction.Descending);
            }

        }
        public bool HandleInput(Input input)
        {
            return HandleInput(input, input.CurrentGamePadState.ThumbSticks.Left);
        }

        public void Show(Vector2 position)
        {
            t.Reset(Direction.Ascending);
            t.OnTransitionEnd = null;
            visible = true;
            drawPosition = position;
        }
        public void Show(PieMenuNode rootNode, Vector2 position)
        {
            this.rootNode = rootNode;
            Show(position);
        }

    }
}
